'use strict';

const path = require('path');
const { spawn } = require('child_process');

const Package = require('@x3-cli-dev/package');
const log = require('@x3-cli-dev/log');

/**
 * 映射表
 */
const SETTINGS = {
  init: '@x3-cli-dev/init',
  publish: '@x3-cli-dev/publish',
  svn: '@x3-cli-dev/svn',
  config: '@x3-cli-dev/config',
  clean: '@x3-cli-dev/clean',
  install: '@x3-cli-dev/install',
  proxy: '@x3-cli-dev/proxy'
};

const CACHE_DIR = 'dependencies';

async function exec() {
  let targetPath = process.env.X3_CLI_TARGET_PATH;
  const homePath = process.env.X3_CLI_HOME_PATH;

  const cmd = arguments[arguments.length - 1];
  const cmdName = cmd.name();
  const packageName = SETTINGS[cmdName];
  const packageVersion = 'latest';
  log.verbose('cmdName', cmdName);
  log.verbose('targetPath', targetPath);
  log.verbose('homePath', homePath);
  log.verbose('packageName', packageName);

  let pkg;
  let storeDir = '';

  if (targetPath) {
    // 使用指定的 targetPath
    pkg = new Package({
      targetPath,
      packageName,
      packageVersion,
    });
  } else {
    targetPath = path.resolve(homePath, CACHE_DIR); // 生成缓存路径
    storeDir = path.resolve(targetPath, 'node_modules');
    log.verbose('storeDir', storeDir);
    pkg = new Package({
      targetPath,
      storeDir,
      packageName,
      packageVersion,
    });

    try {
      if (await pkg.exist()) {
        await pkg.update();
      } else {
        await pkg.install();
      }
    } catch (error) {
      log.error(error.message);
      if (process.env.LOG_LEVEL === 'verbose') {
        log.error('', error);
      }
    }
  }
  const rootFilePath = pkg.getRootFilePath();

  if (rootFilePath) {
    try {
      let tempCmd = Object.create(null);
      Object.keys(cmd).forEach((key) => {
        if (
          cmd.hasOwnProperty(key) &&
          !key.startsWith('_') &&
          !['parent'].includes(key)
        ) {
          tempCmd[key] = cmd[key];
        }
      });
      // 兼容旧的版本从 cmd 中直接获取 options，改为从 cmd._options 中获取
      // 因为 json 序列化无法传递方法
      tempCmd._options = cmd.opts();
      const tempArgs = Array.from(arguments);
      tempArgs[tempArgs.length - 1] = tempCmd;

      // require(rootFilePath).call(null, Array.from(arguments));
      const code = `require('${rootFilePath}').call(null, ${JSON.stringify(
        tempArgs
      )})`;
      const child = spawn('node', ['-e', code], {
        cwd: process.cwd(),
        stdio: 'inherit',
      });
      child.on('error', (error) => {
        log.error(error.message);
        process.exit(1);
      });
      child.on('exit', (error) => {
        log.verbose('命令执行成功:' + error);
        process.exit(error);
      });
    } catch (error) {
      log.error(error.message);
    }
  }
}

module.exports = exec;
